package com.ylr.user.framework.service.impl;

import com.ylr.user.common.constant.UserConstant;
import com.ylr.user.framework.entity.HistoryLoginEntity;
import com.ylr.user.framework.mapper.HistoryLoginMapper;
import com.ylr.user.framework.service.HistoryLoginService;
import com.ylr.base.common.enums.ResultEnum;
import com.ylr.base.common.exception.YlrException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ylr.jwt.framework.service.JwtService;
import com.ylr.base.framework.service.SnowflakeService;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Date;


/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2021-11-05 22:40:00
 * className: HistoryLoginServiceImpl 用户历史登录操作请求接口类实现类
 * version: 1.0
 * description:
 */
@Service("historyLoginService")
@AllArgsConstructor
public class HistoryLoginServiceImpl extends ServiceImpl<HistoryLoginMapper, HistoryLoginEntity> implements HistoryLoginService {

    private static final Logger log = LoggerFactory.getLogger(HistoryLoginServiceImpl.class);

    private final JwtService jwtService;

    private final SnowflakeService snowflakeService;

    @Override
    public void saveUserLogin(Long userId, Integer channel, String loginIP, String requestAddress, Long loginTime,
                              String token, Long expireTime, String refreshToken, Long refreshExpireTime) {
        Date date = new Date();

        HistoryLoginEntity historyLogin = new HistoryLoginEntity();
        // 设置用户id、登录ip、登录时间、过期时间、退出登录时间、更新时间和创建时间属性值
        historyLogin.setId(snowflakeService.getId())
                .setUserId(userId)
                .setChannel(channel)
                .setLoginIp(loginIP)
                .setLoginAddress(requestAddress)
                .setLoginTime(loginTime)
                .setLogoutTime(0L)
                .setToken(token)
                .setExpireTime(expireTime)
                .setRefreshToken(refreshToken)
                .setRefreshExpireTime(refreshExpireTime)
                .setUpdateTime(date)
                .setCreateTime(date);
        // 操作数据库用户历史登录表，新增一条用户登录记录信息
        baseMapper.insert(historyLogin);
        log.info("新增用户登录记录数据完成");
    }

    @Override
    public String checkSingleLogin(Long userId, long now, long expireTime, String loginIP, String requestAddress) {
        String token = null;

//        // 查询数据库，获取用户最新的一条登录记录
//        HistoryLoginEntity historyLogin = this.getLastOneHistoryLoginInfo(userId);
//        if (historyLogin == null) {
//            // 用户从来没有登录过
//            log.info("用户（{}）从来没有登录过", userId);
//
//            // 生成一个新的令牌
//            token = jwtService.createWebToken(userId.toString(), now, expireTime);
//        }
//
//        if (token == null && historyLogin != null && !historyLogin.getToken().equals(Constant.LOGOUT_TOKEN)) {
//            log.info("用户单点登录验证，验证登录ip地址");
//            // 用户处于登录状态
//            if (!loginIP.equals(historyLogin.getLoginIp())) {
//                log.info("用户登录ip（{}）与已经登录的记录ip（{}）不同。", loginIP, historyLogin.getLoginIp());
//                throw new BlogException(HttpConstant.SINGLE_LOGIN, "您的账号处于在线状态，如不是您本人操作，可使用免密登录操作进入网站，并及时修改密码。");
//            }
//            // 同一个客户端，使用不同浏览器进行登录，当前登录记录失效
//            this.userLogout(historyLogin, userId, "用户在浏览器重新登录");
//        }
//        if (token == null) {
//            // 生成一个新的令牌
//            token = jwtUtils.createToken(userId.toString(), now, expireTime);
//        }
//        // 保存一条新的用户登录记录信息
//        this.saveUserLogin(userId, loginIP, requestAddress, token, now, expireTime);

        return token;
    }

//    @Override
//    public void checkSingleLogin(Long userId, SecurityUser securityUser, long nowTime, long expireTime, String loginIP, String requestAddress) {
//        if (securityUser.getLoginIp().equals(loginIP)) {
//
//            // 同一个客户端，使用不同浏览器进行登录，当前登录记录失效
//            this.userLogout(null, userId, "用户在浏览器重新登录");
//
//            // 保存一条新的用户登录记录信息
//            this.saveUserLogin(userId, loginIP, requestAddress, securityUser.getToken(), nowTime, expireTime);
//
//        } else {
//            log.info("用户登录ip（{}）与已经登录的记录ip（{}）不同。", loginIP, securityUser.getLoginIp());
//            throw new BlogException(HttpConstant.SINGLE_LOGIN, "您的账号处于在线状态，如不是您本人操作，可使用免密登录操作进入网站，并及时修改密码。");
//        }
//    }

    @Override
    public HistoryLoginEntity getLastOneHistoryLoginInfo(Long userId) {
        LambdaQueryWrapper<HistoryLoginEntity> historyLoginLambdaWrapper = new LambdaQueryWrapper<>();
        historyLoginLambdaWrapper.select(HistoryLoginEntity::getId, HistoryLoginEntity::getLoginIp,
                HistoryLoginEntity::getToken, HistoryLoginEntity::getLoginTime, HistoryLoginEntity::getExpireTime,
                HistoryLoginEntity::getLogoutTime);
        // 匹配用户id
        historyLoginLambdaWrapper.eq(HistoryLoginEntity::getUserId, userId);
        // 按照历史登录记录主键降序排序
        historyLoginLambdaWrapper.orderByDesc(HistoryLoginEntity::getId);
        // 只查询一个值
        historyLoginLambdaWrapper.last("limit 1");
        // 查询数据库用户历史登录表，获取用户最新的一条登录记录
        return baseMapper.selectOne(historyLoginLambdaWrapper);
    }

    @Override
    public void updateHistoryLogin(HistoryLoginEntity historyLogin) {
        // 更新数据
        int count = baseMapper.updateById(historyLogin);
        if (count == 0) {
            log.info("用户登录记录对象。{}", historyLogin);
            throw new YlrException("修改用户登录记录信息失败，请务必及时处理");
        }
    }

//    @Override
//    public PageDto<HistoryLoginEntity> getUserHistoryLoginList(Integer page) {
//        // 正在获取自己历史登录记录的用户id
//        Long optUserId = UserUtils.getUserId();
//
//        Page<HistoryLoginEntity> pageQuery = new Page<>(page, 10);
//        LambdaQueryWrapper<HistoryLoginEntity> historyLoginLambdaWrapper = new LambdaQueryWrapper<>();
//        // 查询登录ip地址、实际登录地址、登录时间和退出时间字段
//        historyLoginLambdaWrapper.select(HistoryLoginEntity::getLoginIp, HistoryLoginEntity::getLoginAddress,
//                HistoryLoginEntity::getLoginTime, HistoryLoginEntity::getLogoutTime);
//        // 匹配用户id，并且结果按照创建时间降序排序
//        historyLoginLambdaWrapper.eq(HistoryLoginEntity::getUserId, optUserId)
//                .orderByDesc(HistoryLoginEntity::getCreateTime);
//        // 查询数据库用户历史登录记录表，分页查询用户历史登录记录列表
//        this.page(pageQuery, historyLoginLambdaWrapper);
//
//        return new PageDto(pageQuery);
//    }

    @Override
    public void userLogout(HistoryLoginEntity historyLogin, Long userId, String remark) {
        if (historyLogin == null) {
            // 获取用户最新一条登录记录
            historyLogin = this.getLastOneHistoryLoginInfo(userId);
            if (historyLogin == null) {
                log.warn("用户登录记录丢失。userId={}", userId);
                throw new YlrException("用户登录记录丢失，请务必及时处理");
            }
        }
        if (historyLogin.getToken().equals(UserConstant.LOGOUT_TOKEN)) {
            throw new YlrException(ResultEnum.REQUEST_FAIL.getCode(), "您已经退出登录，无需重复操作。");
        }
        Date date = new Date();

        // 设置退出登录时间（时间戳）和更新时间属性值
        historyLogin.setToken(UserConstant.LOGOUT_TOKEN)
                .setLogoutTime(date.getTime())
                .setUpdateTime(date)
                .setRemark(remark);
        // 操作数据库用户历史登录表，更新用户登录记录信息
        baseMapper.updateById(historyLogin);
        log.info("用户退出登录标记成功");
    }

    @Override
    public void userLogoutByExpireTime(Long nowTime) {
        Date date = new Date(nowTime);

        LambdaUpdateWrapper<HistoryLoginEntity> historyLoginLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置 登录令牌、过期时间、退出时间、更新时间和备注 字段值
        historyLoginLambdaUpdateWrapper.set(HistoryLoginEntity::getToken, UserConstant.LOGOUT_TOKEN)
                .set(HistoryLoginEntity::getLogoutTime, date.getTime())
                .set(HistoryLoginEntity::getUpdateTime, date)
                .set(HistoryLoginEntity::getRemark, "系统清空过期的登录记录");
        // 匹配 退出时间和过期时间（‘小于’) 字段
        historyLoginLambdaUpdateWrapper.eq(HistoryLoginEntity::getLogoutTime, 0)
                .lt(HistoryLoginEntity::getExpireTime, nowTime);

        // 操作数据库用户历史登录表，批量清空用户过期登录记录
        baseMapper.update(null, historyLoginLambdaUpdateWrapper);
    }

}